/**
 * @file
 * @author dousha 
 * @date 2020/11/28.
 */

#include "serial.h"
#include "../Logic/serial_state_machine.h"
#include "../Logic/convert.h"
#include <stdint.h>
#include <string.h>

static UART_HandleTypeDef *s = 0;

static uint8_t rxBuffer[SERIAL_RX_SIZE] = {0};
static uint8_t txBuffer[SERIAL_TX_SIZE] = {0};

void serial_init(UART_HandleTypeDef *serial) {
	s = serial;
	memset(rxBuffer, 0, SERIAL_RX_SIZE);
	memset(txBuffer, 0, SERIAL_TX_SIZE);
	HAL_UART_Receive_IT(serial, rxBuffer, 1);
}

void serial_write_crlf() {
	txBuffer[0] = '\r';
	txBuffer[1] = '\n';
	HAL_UART_Transmit(s, txBuffer, 2, HAL_MAX_DELAY);
}

void serial_write_string(const char *str) {
	HAL_UART_Transmit(s, (uint8_t *) str, strlen(str), HAL_MAX_DELAY);
}

void serial_write_bytes(const uint8_t *bytes, uint8_t len) {
	HAL_UART_Transmit(s, (uint8_t *) bytes, len, HAL_MAX_DELAY);
}

void serial_write_byte(uint8_t byte) {
	txBuffer[0] = byte;
	HAL_UART_Transmit(s, txBuffer, 1, HAL_MAX_DELAY);
}

void serial_write_hex(const uint8_t *bytes, size_t len) {
	uint8_t txLen;
	for (size_t i = 0; i < len; i += 8) {
		txLen = 0;
		for (size_t j = 0; j < 16; j += 2) {
			if (i + j / 2 < len) {
				txBuffer[j] = nibble_to_hex(bytes[i + j / 2] / 16);
				txBuffer[j + 1] = nibble_to_hex(bytes[i + j / 2] % 16);
				txLen += 2;
			} else {
				break;
			}
		}
		HAL_UART_Transmit(s, txBuffer, txLen, HAL_MAX_DELAY);
	}
}

void serial_write_u8(uint8_t value) {
	txBuffer[0] = '0' + (value / 100);
	txBuffer[1] = '0' + ((value / 10) % 10);
	txBuffer[2] = '0' + (value % 10);
	HAL_UART_Transmit(s, txBuffer, 3, HAL_MAX_DELAY);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *uart) {
	size_t nextRecvCount = serial_state_machine_handle_input(rxBuffer);
	HAL_UART_Receive_IT(uart, rxBuffer, nextRecvCount);
}
